import axios from 'axios'
import $RefParser from '@apidevtools/json-schema-ref-parser'
import Buffer from 'buffer'
import {
    IApiHandlers,
    IApiItem,
    IImportData,
    IMethod,
} from '../../../../utils/interfaces'
import { randomStr } from '../../../../utils/random'
import { jsonSchemaToMock } from '../jsonSchemaToMock'
// @ts-ignore
window.Buffer = Buffer
// @ts-ignore
Buffer.isBuffer = () => false

// 解析swagger.json，得到dereference后的对象
export const swaggerJsonParse = async (swaggerJson: any) => {
    return $RefParser.dereference(swaggerJson)
}

// 根据tag过滤swagger.json，拿到paths对象
export const filterByTag = (parsed: any, tag?: string) => {
    if (!tag) return parsed.paths
    const pathsArr = Object.keys(parsed.paths)
    const result: Record<string, any> = {}
    pathsArr.filter((path: string) => {
        const pathItem = parsed.paths[path]
        const methods = Object.keys(pathItem)
        const hasTag = methods.some((method: string) =>
            pathItem[method].tags.includes(tag),
        )
        if (hasTag) {
            result[path] = pathItem
        }
    })
    return result
}

// 根据selectedPaths过滤paths对象
export const filterBySelectedPaths = (paths: any, selectedPaths?: string[]) => {
    if (!selectedPaths?.length) return paths
    const result: Record<string, any> = {}
    Object.keys(paths).forEach((path: string) => {
        if (selectedPaths.includes(path)) {
            result[path] = paths[path]
        }
    })
    return result
}

// 配置
export type ISwaggerToGroupConfig = {
    // 根据tag过滤
    filterByTag?: string
    // 选中paths
    selectedPaths?: string[]
    // 导入数据，此数据会在生成apiItem时，同步到apiItem中
    importData?: IImportData
}

// 将swagger.json转换为分组
export const swaggerJsonToApiItems = async (
    swaggerJson: string,
    config?: ISwaggerToGroupConfig,
) => {
    // 解析
    const parsed = await swaggerJsonParse(swaggerJson)
    // 根据tag过滤，拿到paths对象
    let filtered = filterByTag(parsed, config?.filterByTag)
    // 根据selectedPaths过滤
    filtered = filterBySelectedPaths(filtered, config?.selectedPaths)
    // 遍历paths
    const result: IApiItem[] = []
    Object.keys(filtered).forEach((path: string) => {
        const pathItem = filtered[path]
        const methods = Object.keys(pathItem)
        // 遍历methods，生成apiItem
        methods.forEach((_method: string) => {
            const method = _method as IMethod
            const methodItem = pathItem[method]

            let label = methodItem?.summary || path?.split('/').pop() || ''
            if (methodItem?.summary && methodItem?.summary?.length > 20) {
                label = label.slice(0, 20) + '...'
            }

            // 生成api对象
            const apiItem: IApiItem = {
                id: randomStr(),
                label,
                type: 'api',
                method: method.toUpperCase() as IMethod,
                url: path,
                importData: config?.importData
                    ? {
                          ...config.importData,
                          path,
                          method,
                          pathItem,
                      }
                    : undefined,
            }

            // 遍历responses，生成期望
            Object.keys(methodItem.responses).forEach((status: string) => {
                const responseItem = methodItem.responses[status]
                const mock = jsonSchemaToMock(
                    responseItem?.content?.['application/json']?.schema,
                )
                const handlers: IApiHandlers = {
                    resBody: {
                        enabled: true,
                        mockRule: JSON.stringify(mock, null, 2),
                    },
                }
                // 如果是200，则是默认期望
                if (status === '200') {
                    apiItem.handlers = handlers
                } else {
                    if (!apiItem.expects) {
                        apiItem.expects = []
                    }
                    apiItem.expects.push({
                        id: randomStr(),
                        label: status,
                        type: 'expect',
                        handlers,
                    })
                }
            })

            result.push(apiItem)
        })
    })
    return result
}

// 请求swagger.json url
export const fetchSwaggerJson = async (url: string) => {
    const res = await axios.get(url)
    return res.data
}

// 将swagger.json url转换为apiItems
export const swaggerJsonUrlToApiItems = async (
    url: string,
    config?: ISwaggerToGroupConfig,
) => {
    // 获取swagger.json
    const swaggerJson = await fetchSwaggerJson(url)
    return swaggerJsonToApiItems(swaggerJson, {
        ...config,
        importData: {
            mode: 'swagger-json-url',
            url
        },
    })
}

// swaggerJsonUrlToApiItems(
//     'http://swagger-file.changbaops.com/swagger/mario/dev/openapi.json',
//     {
//         filterByTag: 'ArrowHero',
//     },
// )
